﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AutoMapper;
using Rocket.Core.Common;
using System.Linq.Expressions;
using System.Data;

namespace Rocket.Core
{
    public abstract class BaseHandler<V, DTO> : LoggerBase, IHandler<V, DTO>, IMapper<V, DTO>
        where V : BaseObject
        where DTO : class
    {
        private IRepository<DTO> _repository;
        protected IRepository<DTO> Repository
        {
            get { return _repository; }
        }

        protected BaseHandler(IRepository<DTO> repositoryInstance)
        {
            _repository = repositoryInstance;
            ForwardMap(AutoMapper.Mapper.CreateMap<V, DTO>());
            BackwardMap(AutoMapper.Mapper.CreateMap<DTO, V>()
                .ForMember(dest => dest.SourcePoco, Opt => Opt.MapFrom(src => src)));
        }

        public virtual RocketResponse Update(V entity)
        {              
            string mesg = "Operation";
            try
            {
                IObject myObj = ((IObject)entity);

                if (!myObj.IsNew)               
                {
                    _repository.Update(Mapper.Map<V, DTO>(entity, (DTO)myObj.SourcePoco)); 
                    mesg = "Record Updating";
                }
                else
                {
                    _repository.Add(Mapper.Map<V, DTO>(entity));
                    mesg = "Record Adding";
                }

                return new RocketResponse(StatusCodes.Successful
                    , mesg + " is Successfully Completed!!");
            }
            catch (Exception e)
            {
                this.LogError("Error updating record ", e);
                return new RocketResponse(StatusCodes.Failed
                    , mesg + " is Failed" + "\r\nError: " + e.Message);
            }
        } 

        public virtual List<V> GetAll()
        {
            try
            {
                return Mapper.Map<List<DTO>, List<V>>(_repository.GetAll().ToList());
            }
            catch (Exception e)
            {
                this.LogError("Error Getting the records", e);
                return new List<V>();
            }
        }

        public virtual V GetView()
        {
            return null ;
        }

        public virtual List<V> GetAll(Expression<Func<DTO, bool>> whereCondition)
        {
            try
            {
                return Mapper.Map<List<DTO>, List<V>>(_repository.GetAll(whereCondition).ToList());
            }
            catch (Exception e)
            {
                this.LogError("Error Getting the records", e);
                return new List<V>();
            }
        }

        public virtual RocketResponse RemoveAll()
        {
            try
            {
                _repository.DeleteAll();
                return new RocketResponse(StatusCodes.Successful
                    , "Removing All Records is Successfully Completed!!");
            }
            catch (Exception e)
            {
                this.LogError("Error removing record", e);
                return new RocketResponse(StatusCodes.Failed
                    , "Removing Records is Failed"  + "\r\nError: " + e.Message);
            }
        }

        public virtual RocketResponse Remove(long id)
        {
            return null;
        }

        public virtual RocketResponse Remove(V entity)
        {
            try
            {
                IObject myObj = ((IObject)entity);
                _repository.Delete(Mapper.Map<V, DTO>(entity, (DTO)myObj.SourcePoco)); ;
                return new RocketResponse(StatusCodes.Successful, "Removing the Record is Successfully Completed!!");
            }
            catch (Exception e)
            {
                this.LogError("Error removing record", e);
                return new RocketResponse(StatusCodes.Failed
                    , "Removing Record is Failed" + "\r\nError: " + e.Message);
            }
        }
        public abstract void ForwardMap(IMappingExpression<V, DTO> mappingExpression);
        public abstract void BackwardMap(IMappingExpression<DTO, V> mappingExpression);
    }
}
